# UUID类型装饰器
import uuid
import json
from abc import ABC
from datetime import datetime
from typing import Any, Union, List, Optional

from sqlalchemy import Column, DateTime, JSON, TypeDecorator
from sqlalchemy.dialects.mssql.base import MSBinary


class GUID(TypeDecorator):
    impl = MSBinary
    cache_ok = True

    def __init__(self):
        self.impl.length = 16
        TypeDecorator.__init__(self, length=self.impl.length)

    def process_bind_param(self, value: Union[uuid.UUID, Any], dialect="mysql"):
        # 将UUID转为数据库存储格式
        if value is None:
            return None
        if not isinstance(value, uuid.UUID):
            raise TypeError("GUID类型需要uuid作为输入")
        return value.bytes

    def process_result_value(self, value, dialect="mysql"):
        # 从数据库读取时转换回UUID
        if not value:
            return None
        else:
            return uuid.UUID(bytes=value)

    def is_mutable(self):
        return False


class ARRAY(TypeDecorator):
    """
    自定义数组类型，将Python列表存储为JSON字符串
    支持所有数据库（不依赖特定数据库的数组类型）
    """

    impl = JSON  # 底层使用TEXT类型存储
    cache_ok = True  # 对于简单类型可以设为True以提高性能

    def __init__(self, item_type: str = str, dimensions: int = 1, **kwargs):
        """
        参数:
            item_type: 数组元素的类型 (str, int, float等)
            dimensions: 数组维度 (1=一维数组, 2=二维数组等)
        """
        super().__init__(**kwargs)
        self.item_type = item_type
        self.dimensions = dimensions

    def load_dialect_impl(self, dialect):
        return dialect.type_descriptor(JSON())

    def process_bind_param(self, value: List, dialect) -> Optional[str]:
        """将Python列表转换为数据库存储值"""
        if value is None:
            return None
        if not isinstance(value, list):
            raise TypeError("ARRAY类型需要Python列表作为输入")

        # if self.item_type == "UUID":
        #     return json.dumps([str(uuid) for uuid in value])

        return json.dumps(value, ensure_ascii=False)

    def process_result_value(self, value: str, dialect) -> Optional[List]:
        if value is None:
            return None
        try:
            # if self.item_type == "UUID":
            #     str_list = json.loads(value) if isinstance(value, str) else value
            #     return [uuid.UUID(uuid_str) for uuid_str in str_list]
            return json.loads(value) if isinstance(value, str) else value
        except json.JSONDecodeError as e:
            raise ValueError("无效的JSON数组数据") from e

    def copy(self, **kw):
        """创建类型装饰器的拷贝"""
        return ARRAY(self.item_type, self.dimensions, **kw)


class BaseDatabaseModel:
    create_time = Column(DateTime, default=datetime.now, comment="创建时间")
    updated_time = Column(DateTime, default=datetime.now, onupdate=datetime.now, comment="更新时间")

    def to_dict(self, exclude=None):
        """
        将模型转换为字典
        :param exclude: 需要排除的字段列表
        """
        if exclude is None:
            exclude = []
            
        return {
            column.name: getattr(self, column.name)
            for column in self.__table__.columns
            if column.name not in exclude
        }

    def to_json(self):
        """兼容旧版方法"""
        return self.to_dict()

    @classmethod
    def query(cls, reverse=None, order_by=None, **kwargs):
        pass

    @classmethod
    def insert(cls, __data=None, **insert):
        pass


